package com.server.modules.api.service.impl;

import com.server.common.utils.UUIDUtils;
import com.server.modules.api.dao.FriendsAPIDao;
import com.server.modules.api.dao.MemberAPIDao;
import com.server.modules.api.service.IMService;
import com.server.modules.api.utils.Constants;
import com.server.modules.api.utils.HTTPClientUtils;
import com.server.modules.api.utils.HTTPMethod;
import com.server.modules.api.vo.easemob.ClientSecretCredential;
import com.server.modules.api.vo.easemob.EndPoints;
import com.server.modules.sys.dao.friends.FriendsDao;
import com.server.modules.sys.entity.friends.Friends;
import com.server.modules.sys.entity.member.Member;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * REST API Demo :用户体系集成 REST API HttpClient4.3实现
 *
 * Doc URL: https://docs.easemob.com/doku.php?id=start:100serverintegration:20users
 *
 * @author Lynch 2014-09-15
 *
 */
@Service
public class IMServiceImpl implements IMService {

    private Logger logger = Logger.getLogger(IMServiceImpl.class);

    @Autowired
    private FriendsDao friendsDao;
    @Autowired
    private FriendsAPIDao friendsAPIDao;

    @Autowired
    private MemberAPIDao memberAPIDao;
    // 通过app的client_id和client_secret来获取app管理员token
    @Autowired
    private ClientSecretCredential credential;

    /**
     * 注册IM用户[单个]
     *
     * 给指定Constants.APPKEY创建一个新的用户
     *
     * @param userName 登录名
     * @param password  密码
     * @param nickName  昵称
     * @return
     */

    //这个地方你自己改
    @Override
    public Map createNewIMUserSingle(String  userName,String password,String nickName) {
        Map<String,String> param = new HashMap<String,String>();
        param.put("username",userName);
        param.put("password",password);
        param.put("nickname",nickName);
        Map objectNode = HTTPClientUtils.sendHTTPRequest(EndPoints.USERS_URL, credential, param,
                    HTTPMethod.METHOD_POST);
        
        return objectNode;
    }

   /**
    * 注册IM用户[批量]
    *
    * 给指定Constants.APPKEY创建一批用户
    *
    * @param list
    * @return
    */
   public Map<String,Object> createNewIMUserBatch(  List<Map<String,Object>> list) {
	   Map<String,Object> ret=new HashMap<String,Object>();
       // check Constants.APPKEY format
       if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
           logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

           ret.put("message", "Bad format of Constants.APPKEY");

           return ret;
       }

       // check properties that must be provided
           for (Map<String,Object> map : list) {
               if (null != map && !map.containsKey("username")) {
                   logger.error("Property that named username must be provided .");

                   ret.put("message", "Property that named username must be provided .");

                   return ret;
               }
               if (null != map && !map.containsKey("password")) {
                   logger.error("Property that named password must be provided .");

                   ret.put("message", "Property that named password must be provided .");

                   return ret;
               }
           }

       try {
           return HTTPClientUtils.sendHTTPRequest(EndPoints.USERS_URL, credential, list,
                   HTTPMethod.METHOD_POST);

       } catch (Exception e) {
           e.printStackTrace();
       }
	return ret;

   }
   /**
 * @throws MalformedURLException 
    * 
   * @Title: queryChatMessages 
   * @Description: 查询聊天记录
   * @author dingGuangbiao 314667996@qq.com
   * @date 2016-10-26 下午2:30:48 
   * @param @param timestamp 
   * @param @param limit
   * @param @param cursor
   * @param @return 
   * @throws
    */
   public Map queryChatMessages(Long timestamp,Long limit,String cursor,String  lessOrMore)  {
	   //lessOrMore 校验符号
	   if(StringUtils.isBlank(lessOrMore)){
		   return null;
	   }
	   if(!(lessOrMore.equals(">")||lessOrMore.equals("<"))){
		   System.out.println("参数错误");
		   return null;
	   }
	   StringBuilder urlSb=new StringBuilder(Constants.APPKEY.replace("#", "/") + "/chatmessages");
	   if(limit==null){
		   limit=1000l;
	   }
	   urlSb.append("?limit="+limit);
	   if(timestamp!=null){
		 //https://a1.easemob.com/easemob-demo/chatdemoui/chatmessages
		 //?ql=select+*+where+timestamp>1403164734226&limit=20&cursor=MTYxOTcyOTYyNDpnR2tBQVFNQWdHa0FCZ0ZHczBKN0F3Q0FkUUFRYUdpdkt2ZU1FZU9vNU4zVllyT2pqUUNBZFFBUWFHaXZJUGVNRWVPMjdMRWo5b0w4dEFB"
		   urlSb.append("&ql=select+*+where+timestamp"+lessOrMore+timestamp);
	   }
	   if(cursor!=null){
		   urlSb.append("&cursor="+timestamp);
	   }
	   String urlStr = urlSb.toString();
	   URL url=null;
	   URI uri=null;
	try {
		url = new URL(Constants.API_HTTP_SCHEMA, Constants.API_SERVER_HOST, "/" +urlStr);
		uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
		 return HTTPClientUtils.sendHTTPRequest(uri.toURL(), credential, null, HTTPMethod.METHOD_GET);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
      return null;
   }

   /**
    * 注册IM用户[批量生成用户然后注册]
    *
    * 给指定Constants.APPKEY创建一批用户
    *
    * @param usernamePrefix
    *            生成用户名的前缀
    * @param perNumber
    *            批量注册时一次注册的数量
    * @param totalNumber
    *            生成用户注册的用户总数
    * @return
    */
   /*public ObjectNode createNewIMUserBatchGen(String usernamePrefix, Long perNumber, Long totalNumber) {
	   Map<Object,Object> ret=new HashMap<Object,Object>();

       if (totalNumber == 0 || perNumber == 0) {
           return objectNode;
       }
       System.out.println("你即将注册" + totalNumber + "个用户，如果大于" + perNumber + "了,会分批注册,每次注册" + perNumber + "个");
       ArrayNode genericArrayNode = this.genericArrayNode(usernamePrefix, totalNumber);
       if (totalNumber <= perNumber) {
           objectNode = this.createNewIMUserBatch(genericArrayNode);
       } else {

           ArrayNode tmpArrayNode = factory.arrayNode();

           for (int i = 0; i < genericArrayNode.size(); i++) {
               tmpArrayNode.add(genericArrayNode.get(i));
               // 300 records on one migration
               if ((i + 1) % perNumber == 0) {
                   objectNode = this.createNewIMUserBatch(tmpArrayNode);
                   if(objectNode!=null){
                       logger.info("注册IM用户[批量]: " + objectNode.toString());
                   }
                   tmpArrayNode.removeAll();
                   continue;
               }

               // the rest records that less than the times of 300
               if (i > (genericArrayNode.size() / perNumber * perNumber - 1)) {
                   objectNode = this.createNewIMUserBatch(tmpArrayNode);
                   if(objectNode!=null){
                       logger.info("注册IM用户[批量]: " + objectNode.toString());
                   }
                   tmpArrayNode.removeAll();
               }
           }
       }

       return objectNode;
   }*/

   /**
    * 获取IM用户
    *
    * @param userName
    *            用户主键：username或者uuid
    * @return
    */
   public Map getIMUsersByUserName(String userName) {
	   Map<Object,Object> ret=new HashMap<Object,Object>();
       // check Constants.APPKEY format
       if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
           logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

           ret.put("message", "Bad format of Constants.APPKEY");

           return ret;
       }

       // check properties that must be provided
       if (StringUtils.isEmpty(userName)) {
           logger.error("The userName that will be used to query must be provided .");

           ret.put("message", "The userName that will be used to query must be provided .");

           return ret;
       }

       try {

           URL userPrimaryUrl = HTTPClientUtils
                   .getURL(Constants.APPKEY.replace("#", "/") + "/users/" + userName);
           ret = HTTPClientUtils.sendHTTPRequest(userPrimaryUrl, credential, null, HTTPMethod.METHOD_GET);

       } catch (Exception e) {
           e.printStackTrace();
       }

       return ret;
   }

//    /**
//     * 删除IM用户[单个]
//     *
//     * 删除指定Constants.APPKEY下IM单个用户
//     *
//     *
//     * @param userName
//     * @return
//     */
//    public ObjectNode deleteIMUserByuserName(String userName) {
//        ObjectNode objectNode = factory.objectNode();
//
//        // check Constants.APPKEY format
//        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
//            logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);
//
//            objectNode.put("message", "Bad format of Constants.APPKEY");
//
//            return objectNode;
//        }
//
//        try {
//
//            URL deleteUserPrimaryUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users/"
//                    + userName);
//            objectNode = HTTPClientUtils.sendHTTPRequest(deleteUserPrimaryUrl, credential, null,
//                    HTTPMethod.METHOD_DELETE);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        return objectNode;
//    }
//
//    /**
//     * 删除IM用户[批量]
//     *
//     * 批量指定Constants.APPKEY下删除IM用户
//     *
//     * @param limit
//     * @return
//     */
//    public ObjectNode deleteIMUserByUsernameBatch(Long limit) {
//
//        ObjectNode objectNode = factory.objectNode();
//
//        // check Constants.APPKEY format
//        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
//            logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);
//
//            objectNode.put("message", "Bad format of Constants.APPKEY");
//
//            return objectNode;
//        }
//
//        try {
//
//            URL deleteIMUserByUsernameBatchUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users"
//                    + "?limit=" + limit);
//            objectNode = HTTPClientUtils.sendHTTPRequest(deleteIMUserByUsernameBatchUrl, credential, null,
//                    HTTPMethod.METHOD_DELETE);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        return objectNode;
//    }
//
    /**
     * 重置IM用户密码 提供管理员token
     *
     * @param userName
     * @param dataObjectNode
     * @return
     */
    @Override
    public Map modifyIMUserPasswordWithAdminToken(String userName, Map dataObjectNode) {
        Map objectNode = new HashMap();

        // check Constants.APPKEY format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

            objectNode.put("message", "Bad format of Constants.APPKEY");

            return objectNode;
        }

        if (StringUtils.isEmpty(userName)) {
            logger.error("Property that named userName must be provided，the value is username of imuser.");

            objectNode.put("message",
                    "Property that named userName must be provided，the value is username or imuser.");

            return objectNode;
        }

        if (null != dataObjectNode && !dataObjectNode.containsKey("newpassword")) {
            logger.error("Property that named newpassword must be provided .");

            objectNode.put("message", "Property that named newpassword must be provided .");

            return objectNode;
        }

        try {

            URL modifyIMUserPasswordWithAdminTokenUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/")
                    + "/users/" + userName + "/password");
            objectNode = HTTPClientUtils.sendHTTPRequest(modifyIMUserPasswordWithAdminTokenUrl, credential,
                    dataObjectNode, HTTPMethod.METHOD_PUT);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectNode;
    }


    /**
     * 添加好友[单个]
     *
     * @param ownerUserName
     * @param friendUserName
     *
     * @return
     */
    @Override
    public Map addFriendSingle(String ownerUserName, String friendUserName) {
        Map objectNode = new HashMap();
        Member memberA = memberAPIDao.selectByHxUserName(ownerUserName);
        Member memberB = memberAPIDao.selectByHxUserName(friendUserName);
        if (memberA==null||memberB ==null){
             objectNode.put("message","用户信息有误");
            return objectNode;
        }
        Friends friends =  new Friends();
        friends.setFriendAId(memberA.getId());
        friends.setFriendAType("1");
        friends.setFriendBId(memberB.getId());
        friends.setFriendBType("1");
        List<Friends> friendses =friendsAPIDao.getFriend(friends);
        if (friendses!=null && friendses.size()>0){
            objectNode.put("message","你们已经是好友了");
            return objectNode;
        }
        // check Constants.APPKEY format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

            objectNode.put("message", "Bad format of Constants.APPKEY");

            return objectNode;
        }

        if (StringUtils.isEmpty(ownerUserName)) {
            logger.error("Your userName must be provided，the value is username of imuser.");

            objectNode.put("message", "Your userName must be provided，the value is username of imuser.");

            return objectNode;
        }

        if (StringUtils.isEmpty(friendUserName)) {
            logger.error("The userName of friend must be provided，the value is username of imuser.");

            objectNode.put("message",
                    "The userName of friend must be provided，the value is username of imuser.");

            return objectNode;
        }
        try {
            URL addFriendSingleUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users/"
                    + ownerUserName + "/contacts/users/" + friendUserName);

            Map body = new HashMap();
            objectNode = HTTPClientUtils.sendHTTPRequest(addFriendSingleUrl, credential, body, HTTPMethod.METHOD_POST);

        } catch (Exception e) {
            e.printStackTrace();
        }
        friends.setId(UUIDUtils.getUUID());
        friendsDao.insert(friends);
        return objectNode;
    }

    /**
     * 删除好友
     *
     * @param ownerUserName
     * @param friendUserName
     *
     * @return
     */
    @Override
    public Map deleteFriendSingle(String ownerUserName, String friendUserName) {
        Map objectNode = new HashMap();

        // check Constants.APPKEY format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

            objectNode.put("message", "Bad format of Constants.APPKEY");

            return objectNode;
        }

        if (StringUtils.isEmpty(ownerUserName)) {
            logger.error("Your userName must be provided，the value is username of imuser.");

            objectNode.put("message", "Your userName must be provided，the value is username of imuser.");

            return objectNode;
        }

        if (StringUtils.isEmpty(friendUserName)) {
            logger.error("The userName of friend must be provided，the value is username of imuser.");

            objectNode.put("message",
                    "The userName of friend must be provided，the value is username of imuser.");

            return objectNode;
        }

        try {
            URL addFriendSingleUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users/"
                    + ownerUserName + "/contacts/users/" + friendUserName);

            Map body = new HashMap();
            objectNode = HTTPClientUtils.sendHTTPRequest(addFriendSingleUrl, credential, body, HTTPMethod.METHOD_DELETE);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectNode;
    }

    /**
     * 获取用户所有好友
     *
     * @param ownerUserName
     *
     * @return
     */
    @Override
    public Map getFriends(String ownerUserName) {
        Map objectNode = new HashMap<String,String>();

        // check Constants.APPKEY format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Constants.APPKEY: " + Constants.APPKEY);

            objectNode.put("message", "Bad format of Constants.APPKEY");

            return objectNode;
        }

        if (StringUtils.isEmpty(ownerUserName)) {
            logger.error("Your userName must be provided，the value is username of imuser.");

            objectNode.put("message", "Your userName must be provided，the value is username of imuser.");

            return objectNode;
        }

        try {

            URL addFriendSingleUrl = HTTPClientUtils.getURL(Constants.APPKEY.replace("#", "/") + "/users/"
                    + ownerUserName + "/contacts/users");

            Map body = new HashMap();
            objectNode = HTTPClientUtils.sendHTTPRequest(addFriendSingleUrl, credential, body, HTTPMethod.METHOD_GET);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectNode;
    }

    /**
     * IM用户登录
     *
     * @param username
     * @param password
     * @return
     */
    @Override
    public Map imUserLogin(String username, String password) {

        Map objectNode = new HashMap();

        // check appKey format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Appkey: " + Constants.APPKEY);

            objectNode.put("message", "Bad format of Appkey");

            return objectNode;
        }
        if (StringUtils.isEmpty(username)) {
            logger.error("Your username must be provided，the value is username of imuser.");

            objectNode.put("message", "Your username must be provided，the value is username of imuser.");

            return objectNode;
        }
        if (StringUtils.isEmpty(password)) {
            logger.error("Your password must be provided，the value is username of imuser.");

            objectNode.put("message", "Your password must be provided，the value is username of imuser.");

            return objectNode;
        }

        try {
            Map dataNode = new HashMap();
            dataNode.put("grant_type", "password");
            dataNode.put("username", username);
            dataNode.put("password", password);

            objectNode = HTTPClientUtils.sendHTTPRequest(EndPoints.TOKEN_APP_URL, null, dataNode,
                    HTTPMethod.METHOD_POST);

        } catch (Exception e) {
            throw new RuntimeException("Some errors occurred while fetching a token by username and password .");
        }

        return objectNode;
    }


//
//    /*************************************************************************************************************************/
//    /**
//     * 指定前缀和数量生成用户基本数据
//     *
//     * @param usernamePrefix
//     * @param number
//     * @return
//     */
//    public ArrayNode genericArrayNode(String usernamePrefix, Long number) {
//        ArrayNode arrayNode = factory.arrayNode();
//        for (int i = 0; i < number; i++) {
//            ObjectNode userNode = factory.objectNode();
//            userNode.put("username", usernamePrefix + "_" + i);
//            userNode.put("password", Constants.DEFAULT_PASSWORD);
//
//            arrayNode.add(userNode);
//        }
//
//        return arrayNode;
//    }
    /**
     * 发送消息
     *
     * @param targetType
     *            消息投递者类型：users 用户, chatgroups 群组
     * @param target
     *            接收者ID 必须是数组,数组元素为用户ID或者群组ID
     * @param msg
     *            消息内容
     * @param from
     *            发送者
     * @param ext
     *            扩展字段
     *
     * @return 请求响应
     */
    @Override
    public Map sendMessages(String targetType, List<String> target, Map msg, String from,
                                          Map ext) {
        Map objectNode = new HashMap();
        Map dataNode = new HashMap();
        // check appKey format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Appkey: " + Constants.APPKEY);
            objectNode.put("message", "Bad format of Appkey");
            return objectNode;
        }

        // check properties that must be provided
        if (!("users".equals(targetType) || "chatgroups".equals(targetType))) {
            logger.error("TargetType must be users or chatgroups .");
            objectNode.put("message", "TargetType must be users or chatgroups .");
            return objectNode;
        }
        try {
            // 构造消息体
            dataNode.put("target_type", targetType);
            dataNode.put("target", target);
            dataNode.put("msg", msg);
            if(from!=null&&!from.trim().equals("")) {
                dataNode.put("from", from);
            }
            if(ext!=null) {
                dataNode.put("ext", ext);
            }
            logger.info("发送消息:"+dataNode.toString());
            objectNode = HTTPClientUtils.sendHTTPRequest(EndPoints.MESSAGES_URL, credential, dataNode,
                    HTTPMethod.METHOD_POST);

          //  objectNode = (Map) objectNode.get("data");
            logger.info("objecNode:"+objectNode.toString());
//            for (int i = 0; i < target.size(); i++) {
//                String resultStr = objectNode.path(target.path(i).asText()).asText();
//                if ("success".equals(resultStr)) {
//                    logger.error(String.format("Message has been send to user[%s] successfully .", target.path(i)
//                            .asText()));
//                } else if (!"success".equals(resultStr)) {
//                    logger.error(String.format("Message has been send to user[%s] failed .", target.path(i).asText()));
//                }
//            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectNode;
    }

    @Override
    public Map sendSysMessages( List<String> target, Map msg,Map ext) {
        Map objectNode = new HashMap();
        Map dataNode = new HashMap();
        // check appKey format
        if (!HTTPClientUtils.match("^(?!-)[0-9a-zA-Z\\-]+#[0-9a-zA-Z]+", Constants.APPKEY)) {
            logger.error("Bad format of Appkey: " + Constants.APPKEY);
            objectNode.put("message", "Bad format of Appkey");
            return objectNode;
        }
        try {
            // 构造消息体
            dataNode.put("target_type", "users");
            dataNode.put("target", target);
            dataNode.put("msg", msg);
            dataNode.put("from", "客服经理");
            if(ext!=null) {
                dataNode.put("ext", ext);
            }
            logger.info("发送消息:"+dataNode.toString());
            objectNode = HTTPClientUtils.sendHTTPRequest(EndPoints.MESSAGES_URL, credential, dataNode,
                    HTTPMethod.METHOD_POST);
            logger.info("objecNode:"+objectNode.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectNode;
    }

    @Override
    public Member getFriendInfo(String hxName) {
        Member member = memberAPIDao.selectByHxUserName(hxName);
        return  member;
    }
}